
local blankPlayerstats = {agility = 1, agilityexp = 0, acrobatics = 1, acrobaticsexp = 0, barter = 1, barterexp = 0, defense = 1, defenseexp = 0, respect = 0}

function messagePool()
    util.AddNetworkString("sendStats")
end
hook.Add("Initialize", "poolstatmessages", messagePool)

function setStatsOnSpawn(ply)
    timer.Simple(1, function()
        ply:GetTable().Playerstats = ply:GetTable().Playerstats or table.Copy(blankPlayerstats)
        applyArmor(ply)

        local acrobatics = ply:GetTable().Playerstats.acrobatics
        ply:SetJumpPower(160+((acrobatics*4)^1.2))

        local agility = ply:GetTable().Playerstats.agility
        ply:SetRunSpeed(250+((agility*2)^1.5))
        ply:SetWalkSpeed(100+((agility*2)^1.5))

        if string.find(ply:GetUserGroup(), "vip") then
            ply:ChatPrint("You're a VIP!")
            ply:SetRunSpeed(ply:GetRunSpeed() * 1.05)
            ply:SetWalkSpeed(ply:GetWalkSpeed() * 1.05)
            if ply:GetTable().Playerstats.defense<10 then
                ply:SetArmor(255/2)
            end
        end

        if string.find(ply:GetUserGroup(), "goldmember") then
            ply:ChatPrint("You're a Gold Member!")
            ply:SetRunSpeed(ply:GetRunSpeed() * 1.1)
            ply:SetWalkSpeed(ply:GetWalkSpeed() * 1.1)
            ply:SetArmor(255)
        end

    end)
end
hook.Add("PlayerSpawn", "setStatsOnSpawn", setStatsOnSpawn)

function resetPlayerStats(ply)
    if not (ply:IsUserGroup("coowner") or ply:IsUserGroup("devcoowner") or ply:IsUserGroup("owner")) then return end
    for k,v in pairs(player.GetAll()) do
        v:GetTable().Playerstats = table.Copy(blankPlayerstats)
        savePlayerStats(v)
        net.Start("sendStats")
            net.WriteString("all")
            net.WriteTable(v:GetTable().Playerstats)
        net.Send(v)
    end
end
concommand.Add("resetplayerstats", resetPlayerStats)

function GM:PlayerFootstep( ply, pos, foot, sound, volume, rf )
    ply:GetTable().Playerstats = ply:GetTable().Playerstats or table.Copy(blankPlayerstats)
    ply:GetTable().Playerstats.agilityexp = ply:GetTable().Playerstats.agilityexp + 1

     local neededexp = (ply:GetTable().Playerstats.agility*10)^1.6

     //ply:ChatPrint("agilityexp: " .. ply:GetTable().Playerstats.agilityexp)
     //ply:ChatPrint(neededexp)

     local agility = ply:GetTable().Playerstats.agility
     local agilitycap = 20
     
     if (ply:GetTable().Playerstats.agilityexp % 10)==0 then
        savePlayerStats(ply)
        net.Start("sendStats")
            net.WriteString("agility")
            net.WriteString(tostring(ply:GetTable().Playerstats.agility))
            net.WriteString(tostring(ply:GetTable().Playerstats.agilityexp))
        net.Send(ply)
    end

     if (ply:GetTable().Playerstats.agilityexp >= neededexp) and not (ply:GetTable().Playerstats.agility >= 20) then
        ply:GetTable().Playerstats.agility = agility + 1
        ply:GetTable().Playerstats.agilityexp = 0
        ply:SetRunSpeed(250+((agility*2)^1.5))
        ply:SetWalkSpeed(100+((agility*2)^1.5))
        
        net.Start("sendStats")
            //net.WriteString("all")
            //net.WriteTable(ply:GetTable().Playerstats)
            net.WriteString("agility")
            net.WriteString(tostring(ply:GetTable().Playerstats.agility))
            net.WriteString(tostring(ply:GetTable().Playerstats.agilityexp))
        net.Send(ply)
        savePlayerStats(ply)
     elseif ply:GetTable().Playerstats.agility>=agilitycap then
        ply:GetTable().Playerstats.agilityexp = 1000000000
        net.Start("sendStats")
            net.WriteString("agility")
            net.WriteString(tostring(ply:GetTable().Playerstats.agility))
            net.WriteString(tostring(ply:GetTable().Playerstats.agilityexp))
        net.Send(ply)
        savePlayerStats(ply)
    end
 end

 //hook.Add("PlayerFootstep", "runstatsys", PlayerFootstep)

function playerSetSpeed(ply)
    if not ply:IsPlayer() then return end
    ply:GetTable().Playerstats = ply:GetTable().Playerstats or table.Copy(blankPlayerstats)
    local agility = ply:GetTable().Playerstats.agility
    GAMEMODE:SetPlayerSpeed(ply, 100+agility^1.4, 250+agility^1.4)
end
 
hook.Add( "PlayerSpawn", "playerSetSpeedtest", playerSetSpeed )

function applyArmor(ply)
    if not ply:IsPlayer() then return end
    ply:GetTable().Playerstats = ply:GetTable().Playerstats or table.Copy(blankPlayerstats)
    local defense = ply:GetTable().Playerstats.defense
    if defense>=20 then
        timer.Simple(1,function() ply:SetArmor(255) end)
    elseif defense>=15 then
        timer.Simple(1,function() ply:SetArmor(0.75*255) end)
    elseif defense>=10 then
        timer.Simple(1,function() ply:SetArmor(0.50*255) end)
    elseif defense>=5 then
        timer.Simple(1,function() ply:SetArmor(0.25*255) end)
    end
end
 
hook.Add( "PlayerSpawn", "armorapplystats", applyArmor )

function OnPlayerHitGround( ply )
    ply:GetTable().Playerstats.acrobaticsexp = ply:GetTable().Playerstats.acrobaticsexp + 1
    local neededexp = (ply:GetTable().Playerstats.acrobatics*10)^1.6

    local acrobatics = ply:GetTable().Playerstats.acrobatics

    //ply:ChatPrint(ply:GetTable().Playerstats.acrobaticsexp)
    //ply:ChatPrint(neededexp)

     
    if (ply:GetTable().Playerstats.acrobaticsexp % 5)==0 then
        savePlayerStats(ply)
        net.Start("sendStats")
            net.WriteString("acrobatics")
            net.WriteString(tostring(ply:GetTable().Playerstats.acrobatics))
            net.WriteString(tostring(ply:GetTable().Playerstats.acrobaticsexp))
        net.Send(ply)
    end

     if (ply:GetTable().Playerstats.acrobaticsexp >= neededexp) and not (ply:GetTable().Playerstats.acrobatics >= 20) then
        ply:GetTable().Playerstats.acrobatics = acrobatics + 1
        ply:GetTable().Playerstats.acrobaticsexp = 0
        ply:SetJumpPower(160+((acrobatics*4)^1.2))

        net.Start("sendStats")
            net.WriteString("acrobatics")
            net.WriteString(tostring(ply:GetTable().Playerstats.acrobatics))
            net.WriteString(tostring(ply:GetTable().Playerstats.acrobaticsexp))
        net.Send(ply)
        savePlayerStats(ply)
     elseif ply:GetTable().Playerstats.acrobatics >= 20 then
        ply:GetTable().Playerstats.acrobaticsexp = 100000000

        net.Start("sendStats")
            net.WriteString("acrobatics")
            net.WriteString(tostring(ply:GetTable().Playerstats.acrobatics))
            net.WriteString(tostring(ply:GetTable().Playerstats.acrobaticsexp))
        net.Send(ply)
        savePlayerStats(ply)
     end

     //ply:ChatPrint("boom")
 
end

hook.Add("OnPlayerHitGround", "handleJumpstatsys", OnPlayerHitGround)

function doubleJumps(pl, k)
    if not pl or not pl:IsValid() or k~=2 then
        return
    end
         
    if not pl.Jumps or pl:IsOnGround() then
        pl.Jumps=0
    end
     
    if pl.Jumps==3 or (pl.Jumps==2 and pl:GetTable().Playerstats.acrobatics<20) or (pl.Jumps==1 and pl:GetTable().Playerstats.acrobatics<10) then return end
    pl.Jumps = pl.Jumps + 1
    if pl.Jumps==2 or pl.Jumps == 3 then
        local ang = pl:GetAngles()
        local forward, right = ang:Forward(), ang:Right()
         
        local vel = -1 * pl:GetVelocity() -- Nullify current velocity

        vel = vel + Vector(0, 0, pl:GetJumpPower()+30) -- Add vertical force
         
        local spd = pl:GetMaxSpeed()
         
        if pl:KeyDown(IN_FORWARD) then
            vel = vel + forward * spd
        elseif pl:KeyDown(IN_BACK) then
            vel = vel - forward * spd
        end
         
        if pl:KeyDown(IN_MOVERIGHT) then
            vel = vel + right * spd
        elseif pl:KeyDown(IN_MOVELEFT) then
            vel = vel - right * spd
        end
         
        pl:SetVelocity(vel)
    end
end

hook.Add("KeyPress", "DoubleJump", doubleJumps)

function GM:PlayerHurt( ply, attacker, health, damage )
    ply:GetTable().Playerstats = ply:GetTable().Playerstats or table.Copy(blankPlayerstats)
    ply:GetTable().Playerstats.defenseexp = ply:GetTable().Playerstats.defenseexp + damage/4
    local neededexp = (ply:GetTable().Playerstats.defense*10)^1.6

    local defense = ply:GetTable().Playerstats.defense

    if (ply:GetTable().Playerstats.defenseexp >= neededexp) and not (ply:GetTable().Playerstats.defense >= 20) then
        ply:GetTable().Playerstats.defense = defense + 1
        ply:GetTable().Playerstats.defenseexp = 0
     elseif ply:GetTable().Playerstats.defense >= 20 then
        ply:GetTable().Playerstats.defenseexp = 100000000
     end

     savePlayerStats(ply)
     net.Start("sendStats")
        net.WriteString("defense")
        net.WriteString(tostring(ply:GetTable().Playerstats.defense))
        net.WriteString(tostring(ply:GetTable().Playerstats.defenseexp))
    net.Send(ply)
end
//hook.Add("PlayerHurt", "statdamagedfnsadd", PlayerHurt)

function GM:GetFallDamage( ply, speed )
    if speed<800 then return end
    return ( speed^1.2 / 20 / ply:GetTable().Playerstats.defense / ply:GetTable().Playerstats.acrobatics )
 
end


function GM:ScalePlayerDamage(ply, hitgroup, dmginfo)
    if not ply:GetTable().Playerstats.defense then return end

    local defense = ply:GetTable().Playerstats.defense
    dmginfo:ScaleDamage(1-defense/25)
end
//hook.Add("ScalePlayerDamage", "defensestatdoit", ScalePlayerDamage)